﻿using Microsoft.AspNetCore.Http;
using System;
using System.IO;

namespace Coldairarrow.Api
{
    public class DownloadRange
    {

        public HttpContext context = null;
        public HttpRequest request = null;
        public HttpResponse response = null;
        public DownloadRange(HttpContext ctx)
        {
            this.context = ctx;
            this.request = ctx.Request;
            this.response = ctx.Response;
        }
        private int HttpRangeSize = 1024 * 1024; //最大块长度 1M
        public void WriteFile(string file)
        {
            using (var fs = File.OpenRead(file))
            {
                WriteStream(fs);
            }
        }
        private void WriteStream(Stream fs)
        {
            string range = request.Headers["Range"];
            range = range ?? "";
            range = range.Trim().ToLower();
            if (fs.CanSeek)
            {
                if (range.StartsWith("bytes=") && range.Contains("-"))
                {
                    //分段输出文件
                    int start = -1, end = -1;
                    var rgs = range.Substring(6).Split('-');
                    int.TryParse(rgs[0], out start);
                    int.TryParse(rgs[1], out end);
                    if (rgs[0] == "")
                    {
                        start = (int)fs.Length - end;
                        end = (int)fs.Length - 1;
                    }
                    if (rgs[1] == "")
                    {
                        end = (int)fs.Length - 1;
                    }
                    WriteRangeStream(fs, start, end);
                }
                else
                {
                    //输出整个文件
                    int l;
                    byte[] buffer = new byte[40960];
                    while ((l = fs.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        response.Body.Write(buffer, 0, l);
                    }
                }
            }
        }
        private void WriteRangeStream(Stream fs, int start, int end)
        {
            using (fs)
            {
                int rangLen = end - start + 1;
                if (rangLen > 0)
                {
                    if (rangLen > HttpRangeSize)
                    {
                        rangLen = HttpRangeSize;
                        end = start + HttpRangeSize - 1;
                    }
                }
                else
                {
                    throw new Exception("Range error");
                }

                long size = fs.Length;
                //如果是整个文件返回200，否则返回206
                if (start == 0 && end + 1 >= size)
                {
                    response.StatusCode = 200;
                }
                else
                {
                    response.StatusCode = 206;
                }
                // response.Headers.Add("Accept-Ranges", "bytes");
                response.Headers.Add("Content-Range", $"bytes {start}-{end}/{size}");
                response.Headers.Add("Content-Length", rangLen.ToString());

                int readLen, total = 0;
                byte[] buffer = new byte[40960];
                //流定位到指定位置
                try
                {
                    fs.Seek(start, SeekOrigin.Begin);
                    while (total < rangLen && (readLen = fs.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        total += readLen;
                        if (total > rangLen)
                        {
                            readLen -= (total - rangLen);
                            total = rangLen;
                        }
                        response.Body.Write(buffer, 0, readLen);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
    }
}
